package com.synface.facerecognize.library;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.smartshino.face.SsNow;
import com.synface.facerecognize.algorithm.FaceRecognize;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

public class FaceRecognizeAlgorithm
{
  private static final String TAG = FaceRecognizeAlgorithm.class
    .getSimpleName();
  private static final String VERSION = "version";
  private static final String LICENSE_DIR = new StringBuilder()
    .append(Environment.getExternalStorageDirectory()).append("/synjones/idcard").toString();
  private static final String LICENSE_SP_NAME = "facelicense";
  private static final String LICENSE_FILE_PATH = new StringBuilder().append(LICENSE_DIR).append(File.separator).append("faceLicense").toString();
  SsNow algorithm;
  private Context mContext;
  private String mReturnCode;
  private String mVersion = null;

  public FaceRecognizeAlgorithm() {
    this.algorithm = new SsNow();
    String path = new StringBuilder().append(Environment.getExternalStorageDirectory().getPath()).append("").toString();

    this.mReturnCode = this.algorithm.GenAct(0, new byte[16]);
    FaceRecognize.sReturnCode = this.mReturnCode;
    com.synface.utils.Logs.Logs.i(TAG, new StringBuilder().append("返回码：").append(this.mReturnCode).toString());
  }

  public String getVersion() {
    return this.mVersion;
  }

  public String getReturnCode() {
    return this.mReturnCode;
  }

  public SsNow getAlgorithm() {
    return this.algorithm;
  }

  public FaceRecognizeAlgorithm(Context context) {
    this.mContext = context;
    this.algorithm = new SsNow();

    this.mReturnCode = this.algorithm.GenAct(0, new byte[16]);
    FaceRecognize.sReturnCode = this.mReturnCode;
    com.synface.utils.Logs.Logs.i(TAG, new StringBuilder().append("返回码：").append(this.mReturnCode).toString());
  }

  public void initVersion(){
    int[] nMbsz = new int[1];
    int[] nMath = new int[1];
    short[] nAvrsn = new short[4];
    this.algorithm.Version(nMbsz, nMath, nAvrsn);
    com.synface.utils.Logs.Logs.releaseLog(TAG, new StringBuilder().append("nMbsz:").append(nMbsz).append(" nMath:").append(nMath).append(" Version:").append(nAvrsn[0]).append(".").append(nAvrsn[1]).append(".").append(nAvrsn[2]).append(".").append(nAvrsn[3]).toString());

    if (com.synface.utils.StringUtils.isEmpty(this.mVersion)) {
      this.mVersion = new StringBuilder().append(nAvrsn[0]).append(".").append(nAvrsn[1]).append(".").append(nAvrsn[2]).append(".").append(nAvrsn[3]).toString();
    }

  }



  public int activatity(String activationCode) {
    int[] nMbsz = new int[1];
    int[] nMath = new int[1];
    short[] nAvrsn = new short[4];

    this.algorithm.Version(nMbsz, nMath, nAvrsn);
    com.synface.utils.Logs.Logs.releaseLog(TAG, new StringBuilder().append("nMbsz:").append(nMbsz).append(" nMath:").append(nMath).append(" Version:").append(nAvrsn[0]).append(".").append(nAvrsn[1]).append(".").append(nAvrsn[2]).append(".").append(nAvrsn[3]).toString());

    if (com.synface.utils.StringUtils.isEmpty(this.mVersion)) {
      this.mVersion = new StringBuilder().append(nAvrsn[0]).append(".").append(nAvrsn[1]).append(".").append(nAvrsn[2]).append(".").append(nAvrsn[3]).toString();
    }

    try
    {
      if (activationCode.toString().length() != 16) {
        Log.e(TAG, "activationCode length must be 16 bytes");
        return -21;
      }

      String resultString = this.algorithm.GenAct(1, activationCode.toString()
        .getBytes("UTF-8"));

      if (resultString.equals(new String("ok"))) {
        Log.e(TAG, "activate success");
        saveString(LICENSE_SP_NAME, activationCode);
        return 0;
      }
      Log.e(TAG, new StringBuilder().append("activate error:").append(resultString).toString());

      this.mReturnCode = this.algorithm.GenAct(0, new byte[16]);
      Log.e(TAG, new StringBuilder().append("无效激活码: ").append(activationCode.toString()).toString());
      Log.e(TAG, new StringBuilder().append("获取返回码: ").append(this.mReturnCode).append(" 请联系工作人员激活").toString());
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    return -19;
  }

  public int loadAssetFile() {
    try {
      String sdmdat = new StringBuilder().append(this.mContext.getFilesDir().getAbsolutePath()).append("/Face.dat").toString();

      String version = getString("version");
      com.synface.utils.Logs.Logs.i(TAG, new StringBuilder().append("version:").append(version).toString());
      if (!version.equals(this.mVersion)) {
        boolean delete = new File(sdmdat).delete();
        com.synface.utils.Logs.Logs.releaseLog(TAG, new StringBuilder().append("delete dat:").append(delete).toString());
        saveString("version", this.mVersion);
      }
      if (!new File(sdmdat).exists())
      {
        InputStream is = this.mContext.getResources().getAssets()
          .open("Face.dat");

        FileOutputStream fos = new FileOutputStream(sdmdat);
        byte[] buffer = new byte[1024];
        int count = 0;
        while ((count = is.read(buffer)) > 0) {
          fos.write(buffer, 0, count);
        }
        fos.close();
        is.close();
      }
      int loadresult = this.algorithm.LodDat(sdmdat);
      com.synface.utils.Logs.Logs.releaseLog(TAG, new StringBuilder().append("加载算法数据库完成:").append(loadresult).toString());
      return loadresult;
    } catch (Exception e) {
      com.synface.utils.Logs.Logs.releaseLog(TAG, "加载算法数据库失败，程序异常");
      e.printStackTrace();
    }return -4;
  }

  public int unloadAssetFile(Context mContext)
  {
    try {
      int loadresult = this.algorithm.LodDat(null);
      com.synface.utils.Logs.Logs.releaseLog(TAG, new StringBuilder().append("卸载算法数据库完成:").append(loadresult).toString());
      return loadresult;
    } catch (Exception e) {
      com.synface.utils.Logs.Logs.releaseLog(TAG, "卸载算法数据库失败，程序异常");
      e.printStackTrace();
    }return -4;
  }

  public void deinit(long currentThreadNum)
  {
    this.algorithm.Close(currentThreadNum);
  }

  public int init(long[] multithreadSupport) {
    long[] temp = new long[1];
    int threadNum = 0;
    int result = 0;
    com.synface.utils.Logs.Logs.releaseLog(TAG, new StringBuilder().append("需要初始化的句柄个数是 ").append(multithreadSupport.length).toString());
    while (threadNum < multithreadSupport.length) {
      result = this.algorithm.Init(temp);
      if (result < 0) {
        break;
      }
      multithreadSupport[threadNum] = temp[0];
      com.synface.utils.Logs.Logs.releaseLog(TAG, new StringBuilder().append("初始化其中一个 ").append(multithreadSupport[threadNum]).toString());
      ++threadNum;
    }
    return result;
  }

  public int getFeature(byte[] feature, Bitmap bitmap, long currentThreadNum) {
    com.synface.utils.Logs.Logs.debugLog("getFeature", new StringBuilder().append("getFeature currentThreadNum = ")
      .append(String.valueOf(currentThreadNum))
      .toString());
    long start = System.currentTimeMillis();
    int result = this.algorithm.Minutia(feature, bitmap, 0, currentThreadNum);
    long end = System.currentTimeMillis();
    Log.e(TAG, new StringBuilder().append("花费时间111:").append(end - start).toString());
    Log.d(TAG, new StringBuilder().append("result=").append(result).toString());
    return result;
  }

  public int getFeatureByData(byte[] feature, byte[] data, int width, int height, long currentThreadNum)
  {
    com.synface.utils.Logs.Logs.debugLog("getFeature", new StringBuilder().append("getFeatureByData currentThreadNum = ")
      .append(String.valueOf(currentThreadNum))
      .toString());
    int[] hAttr = { width, height, 0, 0 };
    int result = this.algorithm.FeatureX(feature, data, hAttr, 0, currentThreadNum);

    return result;
  }

  public int compareFeature(byte[] feature1, byte[] feature2, long currentThreadNum)
  {
    int result = this.algorithm.Match(feature1, feature2, 0, currentThreadNum);
    return result;
  }

  public int isGranted()
  {
    if (isGrantedBySharedPreferences()) {
      return 0;
    }

    if (isGrantedByDisk()) {
      return 0;
    }

    if (isGrantedByAssets()) {
      return 0;
    }
    return -19;
  }

  private boolean isGrantedByAssets() {
    com.synface.utils.Logs.Logs.debugLog(TAG, "从assets中搜索授权码...");
    String[] licenses = getLicensesFromAssets();
    if ((licenses == null) || (licenses.length == 0))
      return false;
    for (String code : licenses)
    {
      if (activatity(code) == 0) {
        saveString(LICENSE_SP_NAME, code);
        return true;
      }
    }
    return false;
  }

  private boolean isGrantedByDisk() {
    com.synface.utils.Logs.Logs.releaseLog(TAG, "本地文件查找授权码...");
    File file = new File(LICENSE_DIR);
    if ((!file.exists()) || (!file.isDirectory())) {
      file.mkdir();
    }
    String[] licensesByDisk = getLicensesFromDisk();
    if ((licensesByDisk == null) || (licensesByDisk.length == 0))
      return false;
    for (String code : licensesByDisk)
    {
      if (activatity(code) == 0) {
        saveString(LICENSE_SP_NAME, code);
        return true;
      }
    }
    return false;
  }

  private boolean isGrantedBySharedPreferences() {
    com.synface.utils.Logs.Logs.releaseLog(TAG, "SharedPreferences查找授权码...");
    String license = getString(LICENSE_SP_NAME);
    com.synface.utils.Logs.Logs.releaseLog(TAG, "SharedPreferences2查找授权码...");
    if ((!com.synface.utils.StringUtils.isBlank(license)) &&
      (activatity(license) == 0)) {
      return true;
    }
    com.synface.utils.Logs.Logs.releaseLog(TAG, "SharedPreferences没找到授权码...");
    return false;
  }

  private static String[] getLicensesFromDisk() {
    StringBuilder fileContent = com.synface.utils.FileUtils.readFile(LICENSE_FILE_PATH, "UTF-8");

    return (fileContent == null) ? null : fileContent.toString().split(",");
  }

  private String[] getLicensesFromAssets()
  {
    StringBuilder fileContent = new StringBuilder("");
    try
    {
      InputStream is = this.mContext.getResources().getAssets()
        .open("license");

      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      String line;
      while ((line = reader.readLine()) != null)
      {

        if (!fileContent.toString().equals("")) {
          fileContent.append("\r\n");
        }
        fileContent.append(line);
      }
      reader.close();
    } catch (IOException e) {
      return null;
    }
    BufferedReader reader;
    return fileContent.toString().split(",");
  }

  private Map<String, String> getMapFromFile()
  {
    Map map = new HashMap();

    StringBuilder fileContent = new StringBuilder("");
    try
    {
      InputStream is = this.mContext.getResources().getAssets()
        .open("license");

      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      String line;
      while ((line = reader.readLine()) != null)
      {
        if (!fileContent.toString().equals("")) {
          fileContent.append("\r\n");
        }
        fileContent.append(line);
      }
      reader.close();
    } catch (IOException e) {
      return map;
    }
    BufferedReader reader;
    map = com.synface.utils.JSONUtils.parseKeyAndValueToMap(fileContent.toString());
    return map;
  }

  public void saveString(String key, String value) {
    SharedPreferences sharedPreferences = this.mContext.getSharedPreferences("info", 0);

    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(key, value);
    editor.commit();
  }

  public String getString(String key) {
    SharedPreferences sharedPreferences = this.mContext.getSharedPreferences("info", 0);

    return sharedPreferences.getString(key, "");
  }

  private String getDeviceId(Context context)
  {
    TelephonyManager TelephonyMgr = (TelephonyManager)context
      .getSystemService("phone");

    String szImei = TelephonyMgr.getDeviceId();
    return (szImei == null) ? "" : szImei;
  }

  private String getDevice() {
    return Build.DEVICE;
  }

  private String getAndroidId(Context context)
  {
    String m_szAndroidID = Settings.Secure.getString(context
      .getContentResolver(), "android_id");
    return (m_szAndroidID == null) ? "" : m_szAndroidID;
  }

  public static String getLocalMacAddressFromWifiInfo(Context context)
  {
    WifiManager wm = (WifiManager)context.getSystemService("wifi");

    String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();
    return (m_szWLANMAC == null) ? "" : m_szWLANMAC;
  }

  public int getFaceAttr(int[] hFattr, Bitmap bitmap, long currentThreadNum) {
    com.synface.utils.Logs.Logs.debugLog("getFacePosition", new StringBuilder().append("getFacePosition currentThreadNum = ")
      .append(String.valueOf(currentThreadNum))
      .toString());
    long start = System.currentTimeMillis();
    int tcInt = this.algorithm.Discover(hFattr, bitmap, 0, currentThreadNum);
    long end = System.currentTimeMillis();
    com.synface.utils.Logs.Logs.debugLog(TAG, new StringBuilder().append("result=").append(tcInt).toString());
    return tcInt;
  }
}